home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_c
/
cuj0696.zip
/
DWYER.ZIP
/
COUPON.TST
/
SETCUPN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-08
|
8KB
|
219 lines
/* ============ */
/* setcupn.c */
/* ============ */
#include <defcodes.h>
#include <miscdefs.h>
#include <cupndefs.h>
#include <math.h>
#define ACT(X) #X
#define CLAMP(Var, Lo, Hi) __min(Hi, __max(Lo, Var))
#define NEED_MAX_CPN_LEN(LO, HI) \
"Enter Maximum Segment Length ["ACT(LO)"-"ACT(HI)"]: "
#define NEED_MIN_CELL_EXPECT(LO, HI) \
"Enter Minimum Cell Expectation ["ACT(LO)"-"ACT(HI)"]: "
#define NEED_NUMBER_COUPONS(LO, HI) \
"Enter Number of Coupons to be Collected ["\
ACT(LO)"-"ACT(HI)"]: "
#define NEED_UNIQUE_COUPON_INTEGERS(LO, HI) \
"Enter Number Unique Integers in a Coupon ["\
ACT(LO)"-"ACT(HI)"]: "
#define REPORT_USER_INT_ENTRY(Entry, Label) \
{ \
fflush(NULL); printf("\n"); \
printf("\tNumber Entered: %.f", (double)Entry);\
printf(" (%s)\n", Label); \
}
#define SHOW_INT_VALUE_USED(Entered, Used) \
printf("\tTest Value Used: %.f%s\n", (double)Used, \
((double)Entered == (double)Used) ? "" : " (Clamped)")
/* ------------------- */
/* FUNCTION PROTOTYPES */
/* ------------------- */
# undef F
# if defined(__STDC__) || defined(__PROTO__)
# define F( P ) P
# else
# define F( P ) ()
# endif
/* INDENT OFF */
static void CupnMeanStdDev F((unsigned int, double *, double *));
extern void SetCouponControls F((COUPON_DATA_STRU *));
# undef F
/* INDENT ON */
static double CellExpect[MAX_COUPON_LEN];
static double CouponProbs[MAX_COUPON_LEN];
/* ==================================================================== */
/* SetCouponControls - Puts Run Controls in CouponData structure */
/* ==================================================================== */
void
SetCouponControls(COUPON_DATA_STRU *CouponData)
{
int k, NewlineCh;
char Prompt[64];
int UserIntEntry;
long UserLongEntry;
NewlineCh = _isatty(_fileno(stdin)) ? '\r' : '\n';
/* ------------------------------------- */
/* Request Number Integers in Coupon Set */
/* ------------------------------------- */
GetInt(NEED_UNIQUE_COUPON_INTEGERS(MIN_SET_SIZE, MAX_SET_SIZE),
&UserIntEntry);
REPORT_USER_INT_ENTRY(UserIntEntry,
"Number Unique Integers in a Coupon");
CouponData->SetSize = CLAMP(UserIntEntry, MIN_SET_SIZE, MAX_SET_SIZE);
SHOW_INT_VALUE_USED(UserIntEntry, CouponData->SetSize);
fflush(NULL);fprintf(stderr, "%c", NewlineCh);
/* ------------------------------------------- */
/* Request Maximum Coupon Length to be Tallied */
/* ------------------------------------------- */
{
int MinCpnLen = CouponData->SetSize + 6;
sprintf(Prompt, "Enter Maximum Segment Length [%d-%d]: ",
MinCpnLen, MAX_COUPON_LEN);
GetInt(Prompt, &UserIntEntry);
REPORT_USER_INT_ENTRY(UserIntEntry, "Maximum Segment Length");
CouponData->MaxCpnLen =
CLAMP(UserIntEntry, MinCpnLen, MAX_COUPON_LEN);
SHOW_INT_VALUE_USED(UserIntEntry, CouponData->MaxCpnLen);
}
fflush(NULL);fprintf(stderr, "%c", NewlineCh);
/* -------------------------------------- */
/* Calculate & Store Number of Categories */
/* -------------------------------------- */
CouponData->NumCategories =
CouponData->MaxCpnLen - CouponData->SetSize + 1;
/* -------------------------------- */
/* Request Minimum Cell Expectation */
/* -------------------------------- */
GetInt(NEED_MIN_CELL_EXPECT(MIN_CELL_XPCT, MAX_CELL_XPCT),
&UserIntEntry);
REPORT_USER_INT_ENTRY(UserIntEntry, "Minimum Cell Expectation");
/* ---------------- */
/* Clamp CellExpect */
/* ---------------- */
CouponData->UserCellExpect =
__min(MAX_CELL_XPCT, __max(MIN_CELL_XPCT, UserIntEntry));
SHOW_INT_VALUE_USED(UserIntEntry, CouponData->UserCellExpect);
fflush(NULL);fprintf(stderr, "%c", NewlineCh);
/* ----------------------------------------------------------- */
/* Calculate Probabilities Based on Data Width & Coupon Length */
/* ----------------------------------------------------------- */
CalcCouponProbs(CouponData->SetSize, CouponData->MaxCpnLen,
CouponProbs);
/* ------------------------------------------------------ */
/* Compute Number Coupons Needed to Deliver Ideal Minimum */
/* ------------------------------------------------------ */
CouponData->IdealNumCoupons = (long)
ceil((double)MIN_CELL_XPCT/CouponProbs[0]);
/* ------------------------------------------------------ */
/* Compute Number Coupons Needed to Deliver Users Minimum */
/* ------------------------------------------------------ */
CouponData->UserNumCoupons = (long)
ceil(CouponData->UserCellExpect/CouponProbs[0]);
/* ---------------------------------------------------- */
/* Get User-Specified Number of Coupons to Be Collected */
/* ---------------------------------------------------- */
sprintf(Prompt, "How Many Coupons Are To Be Collected?"
" [%ld ...]: ",
(long)__max(MIN_NUM_COUPONS, CouponData->UserNumCoupons));
GetLong(Prompt, &UserLongEntry);
REPORT_USER_INT_ENTRY(UserLongEntry,
"Number of Coupons to be Counted");
CouponData->NumCoupons = (int)
CLAMP(UserLongEntry, MIN_NUM_COUPONS, MAX_NUM_COUPONS);
SHOW_INT_VALUE_USED(UserLongEntry, CouponData->NumCoupons);
fflush(NULL);fprintf(stderr, "%c", NewlineCh);
/* -------------------------------------------------- */
/* Calculate Cell Expectations Based on Probabilities */
/* -------------------------------------------------- */
for (k = 0; k < CouponData->NumCategories; ++k)
{
CellExpect[k] = CouponProbs[k] * CouponData->NumCoupons;
P(printf("CellExpect[%2d] = %.11g\n", k, CellExpect[k]));
}
/* -------------------------------------------------- */
/* Lump lower-valued categories into next higher ones */
/* -------------------------------------------------- */
CouponData->NotEnough = 0;
for (k = 0; k < CouponData->NumCategories - 1; ++k)
{
if (CellExpect[k] < CouponData->UserCellExpect)
{
++CouponData->NotEnough;
CellExpect[k+1] += CellExpect[k];
CellExpect[k] = 0;
}
}
CouponData->CellExpect = CellExpect;
/* ------------------------------ */
/* Set Generator Failure Count to */
/* A Priori Mean + 6 * Std Dev. */
/* ------------------------------ */
{
double CpnMean, CpnStdDev;
CupnMeanStdDev(CouponData->SetSize, &CpnMean, &CpnStdDev);
CouponData->MaxGenPerSeg = (long)
(ceil(CpnMean) +
100 * ceil(CpnStdDev));
}
printf("\nFailure Count = %ld\n", CouponData->MaxGenPerSeg);
printf("\tA Complete Coupon Should Have Been\n"
"\tCollected Within This Many Variates.\n");
P(printf("NotEnough = %d\n", CouponData->NotEnough));
CouponData->CallStatusOK = (CouponData->NotEnough == 0);
}
/* ==================================================================== */
/* CupnMeanStdDev - Calculates Coupon-Width Mean & Standard Deviation */
/* ==================================================================== */
static void
CupnMeanStdDev(UINT Width, double *Mean, double *StdDev)
{
/* --------------------------------------------------------- */
/* Width is maximum number of unique integers in a data set. */
/* These equations were taken from D. E. Knuth, "The Art of */
/* Computer Programming," Volume 2, Seminumerical Algorithms */
/* (1981), page 536 (top). */
/* --------------------------------------------------------- */
*Mean = Width * (CalcHarm(1, Width) - 1);
*StdDev = sqrt(SQR((double)Width) * (CalcHarm(2, Width) - 1)
- *Mean);
}